package za.ac.wits.elen7045.persistence.encryption;

import java.io.IOException;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.PBEParameterSpec;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;
import za.ac.wits.elen7045.persistence.exception.EncryptionException;

public abstract class TwoWayEncryptor implements Encryptor {

    private final byte[] SALT = {
        (byte) 0xde, (byte) 0x33, (byte) 0x10, (byte) 0x12,
        (byte) 0xde, (byte) 0x33, (byte) 0x10, (byte) 0x12,
    };
    private String algorithm;
	private Cipher cipher;
	private SecretKey secretKey;
	
	public TwoWayEncryptor(String algorithm) {
		this.algorithm = algorithm;
		try {
	        SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(algorithm);
	        secretKey = keyFactory.generateSecret(new PBEKeySpec(getPassword().toCharArray()));
		} catch (Exception e) {
			throw new EncryptionException(e);
		}
	}
	
	protected abstract String getPassword();

	protected Cipher getCipher(int encrypMode) {
		try {
			cipher = Cipher.getInstance(algorithm);
	        cipher.init(encrypMode, secretKey, new PBEParameterSpec(SALT, 20));
			return cipher;
		} catch (Exception e) {
			throw new EncryptionException(e);
		}
	}
	
	protected SecretKey getSecretKey() {
		return secretKey;
	}
	
	/* Utilities */
	
    protected String base64Encode(byte[] bytes) {
        return new BASE64Encoder().encode(bytes);
    }

    protected byte[] base64Decode(String property) throws IOException {
		return new BASE64Decoder().decodeBuffer(property);
    }

}
